package com.bonc.event.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.apporiented.algorithm.clustering.Cluster;
import com.bonc.classifier.maxent.EventClassifier;
import com.bonc.classifier.maxent.MaxentTrainer;
import com.bonc.clustering.EventCluster;
import com.bonc.event.eventtype.EventTypeClassifier;
import com.bonc.event.eventtype.EventTypeTrainer;
import com.bonc.event.model.BONCEvent;
import com.bonc.event.model.BONCEventArgument;
import com.bonc.event.service.IEventRecognitionService;
import com.bonc.text.entity.recognition.RecResult;
import com.bonc.text.service.impl.EntityRecognitionServiceImpl;
import com.bonc.utilities.EventUtility;
import com.bonc.vectorspace.model.EventDocument;

/**
 * @author donggui@bonc.com.cn
 * @version 2016 2016年6月28日 上午10:03:33
 */
@Service
public class EventRecognitionService implements IEventRecognitionService{

	@Autowired	
	MaxentTrainer maxentTrainer;
	
	@Autowired
	EventTypeTrainer eventTypeTrainer;
	
	@Autowired
	EntityRecognitionServiceImpl entityRecognitionService;
	
	public Map<String, String> stopwords = EventUtility.loadStopwords();
	
	public EventRecognitionService(){
		if(maxentTrainer ==null){
			initClassifier();
		}
		
		if(entityRecognitionService ==null){
			entityRecognitionService = new EntityRecognitionServiceImpl();
		}
	}
	
	private void initClassifier(){
		String trainingDirname ="D:\\workspace\\extractor\\data\\trainingCorpus\\";
		String modelFilename = "D:\\workspace\\extractor\\model\\event.model";
//		File trainingFile = new File(trainingDirname);
//		File modelFile = new File(modelFilename);
		//如果dir对应的文件不存在，或者不是一个目录，则退出
		maxentTrainer = new MaxentTrainer(trainingDirname, modelFilename);
//			classifier = maxentTrainer.TrainMaxent(trainingFile, modelFile);	
		
		String type_trainingDirname ="D:\\workspace\\extractor\\data\\eventType\\training\\";
		String type_modelFilename = "D:\\workspace\\extractor\\model\\eventtype.model";
		eventTypeTrainer = new EventTypeTrainer();
		eventTypeTrainer.TrainEventType(type_trainingDirname,type_modelFilename);
	}

	/* (non-Javadoc)
	 * @see com.bonc.event.service.IEventRecognitionService#getEventList(java.lang.String)
	 */
	public List<BONCEvent> getEventList(String content) {
		//		List<BONCEventMention> eventMentions = new ArrayList<BONCEventMention>();
		List<BONCEvent> events = new ArrayList<BONCEvent>();
		if(content!=null && !"".equals(content.trim())){
			List<EventDocument> documents = EventUtility.convertText2Document(content.trim(),null);
			System.out.println("test2=="+documents.size());
			//classify
			List<String> targetValues = EventClassifier.predictEvent(maxentTrainer.getClassifier(),
					maxentTrainer.getFeatureTerms(), documents);
			System.out.println("test3=="+targetValues.size());

			List<Integer> indices = new ArrayList<Integer>();
			for(int k = 0; k<targetValues.size(); k++){
				if(targetValues.get(k) == "pos"){
					indices.add(k);
				}
			}
			System.out.println("test4==indices.size: "+indices.size());
			if(indices!=null && indices.size()>1){
				//cluster
				Cluster parentCluster = EventCluster.runCluster(documents, indices);
				System.out.println("test5=="+parentCluster.getChildren().size());
				
//				List<Cluster> chosenClusters =parentCluster.getChildren();
				List<Cluster> chosenClusters = EventCluster.getClustersInferior(parentCluster);
//				System.out.println("test7==eventContent: "+eventContent);

				int event_index = 0;
				for(Cluster cluster:chosenClusters){
					String eventContent = getAllLeavesContent(documents, cluster);
//					System.out.println("test7==eventContent: "+eventContent);
					if(eventContent!=null && !"".equals(eventContent.trim())){
						eventContent = eventContent.trim();
						
						//entity
						BONCEvent event = new BONCEvent();						
						eventContent = eventContent.replaceAll("　　", "");
						event.setText(eventContent);
						event.setId(String.valueOf(event_index));
						event.setDistance(cluster.getDistanceValue());
						
						//type
						String type = EventTypeClassifier.predictEventType(eventTypeTrainer, eventContent,stopwords);
						if(type!=null){
							event.setType(type);
						}
						
						//eventContents.add(eventContent);
						List<RecResult> names = entityRecognitionService.getEntityList(eventContent);
						for(RecResult name:names){
							if(name!=null){
								BONCEventArgument argument = new BONCEventArgument(name.getWord(),name.getTypeName());
								event.addArgument(argument);
							}
						}
						if(event!=null){
							events.add(event);
						}
						event_index ++;
					}
				}				
			}else{
				if(indices!=null && indices.size()==1){
					BONCEvent event = new BONCEvent();
					String eventContent = documents.get(indices.get(0)).getContent();
					event.setText(eventContent);
					event.setId("0");
					//type
					String type = EventTypeClassifier.predictEventType(eventTypeTrainer, eventContent,stopwords);
					if(type!=null){
						event.setType(type);
					}
					
					List<RecResult> names = entityRecognitionService.getEntityList(event.getText());
					for(RecResult name:names){
						if(name!=null){
							BONCEventArgument argument = new BONCEventArgument(name.getWord(),name.getTypeName());
							event.addArgument(argument);
						}
					}
					if(event!=null){
						events.add(event);
					}					
				}

			}

		}
		return events;
	}
	
	private String getAllLeavesContent(List<EventDocument> documents, Cluster cluster){
		if(cluster!=null){
			String leavesContent = "";
			if(cluster.isLeaf()){
				String docId = cluster.getName();
//				leavesContent +=  documents.get(Integer.valueOf(docId)).toString() +"\n";
				leavesContent +=  documents.get(Integer.valueOf(docId)).getContent() +"。";
			}else{
				for(Cluster child:cluster.getChildren()){
					leavesContent += getAllLeavesContent(documents, child);
				}				
			}
			return leavesContent ;
		}
		return null;
	}

}
